From e6f02f3a178e221766abfa2162016648f047db94 Mon Sep 17 00:00:00 2001 From: robertlipe Date: Mon, 12 May 2014 00:08:59 +0000 Subject: [PATCH] =?utf8?q?Koles=C3=A1r=20Andr=C3=A1s=20adds=20faster=20Gar?= =?utf8?q?min=20serial=20download=20speed=20option.?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- gpsbabel/garmin.cc | 33 +++++++ gpsbabel/gbser_posix.cc | 2 +- gpsbabel/jeeps/gps.h | 1 + gpsbabel/jeeps/gpsapp.cc | 31 ++++++- gpsbabel/jeeps/gpsapp.h | 1 + gpsbabel/jeeps/gpscom.cc | 2 +- gpsbabel/jeeps/gpsserial.cc | 92 ++++++++++++++++++- gpsbabel/jeeps/gpsserial.h | 3 +- gpsbabel/jeeps/gpsusbread.cc | 2 +- gpsbabel/jeeps/gpsusbsend.cc | 2 +- .../xmldoc/formats/options/garmin-baud.xml | 28 ++++++ 11 files changed, 185 insertions(+), 12 deletions(-) create mode 100644 gpsbabel/xmldoc/formats/options/garmin-baud.xml diff --git a/gpsbabel/garmin.cc b/gpsbabel/garmin.cc index d2489fbff..bb629a452 100644 --- a/gpsbabel/garmin.cc +++ b/gpsbabel/garmin.cc @@ -26,6 +26,7 @@ #include "defs.h" #include "grtcirc.h" #include "jeeps/gps.h" +#include "jeeps/gpsserial.h" #include "garmin_tables.h" #include "garmin_fs.h" #include "garmin_device_xml.h" @@ -48,6 +49,8 @@ static char* snwhiteopt = NULL; static char* deficon = NULL; static char* category = NULL; static char* categorybitsopt = NULL; +static char* baudopt = NULL; +static int baud = 0; static int categorybits; static int receiver_must_upper = 1; @@ -93,6 +96,10 @@ arglist_t garmin_args[] = { "bitscategory", &categorybitsopt, "Bitmap of categories", NULL, ARGTYPE_INT, "1", "65535" }, + { + "baud", &baudopt, "Speed in bits per second of serial port (baud=9600)", + NULL, ARGTYPE_INT, ARG_NOMINMAX }, + ARG_TERMINATOR }; @@ -139,11 +146,31 @@ rw_init(const char* fname) categorybits = strtol(categorybitsopt, NULL, 0); } + if (baudopt) { + baud = strtol(baudopt, NULL, 0); + switch (baud) { + case 9600: + case 19200: + case 38400: + case 57600: + case 115200: + break; + default: + fatal("Baud rate %d is not supported\n", baud); + } + } + if (GPS_Init(fname) < 0) { fatal(MYNAME ":Can't init %s\n", fname); } portname = fname; + if (baud && baud != DEFAULT_BAUD) { + if (0 == GPS_Set_Baud_Rate(portname, baud)) { + gps_baud_rate = baud; + } + } + /* * Grope the unit we're talking to to set setshort_length to * 20 for the V, @@ -314,6 +341,12 @@ rd_init(const char* fname) static void rw_deinit(void) { + if (gps_baud_rate != DEFAULT_BAUD) { + if (0 == GPS_Set_Baud_Rate(portname, DEFAULT_BAUD)) { + gps_baud_rate = baud; + } + } + if (mkshort_handle) { mkshort_del_handle(&mkshort_handle); } diff --git a/gpsbabel/gbser_posix.cc b/gpsbabel/gbser_posix.cc index b4939b095..3ae1522a3 100644 --- a/gpsbabel/gbser_posix.cc +++ b/gpsbabel/gbser_posix.cc @@ -51,7 +51,7 @@ static gbser_handle* gbser__get_handle(void* p) return h; } -static speed_t mkspeed(unsigned br) +speed_t mkspeed(unsigned br) { switch (br) { case 1200: diff --git a/gpsbabel/jeeps/gps.h b/gpsbabel/jeeps/gps.h index 7da64b6be..ddcc1b654 100644 --- a/gpsbabel/jeeps/gps.h +++ b/gpsbabel/jeeps/gps.h @@ -276,6 +276,7 @@ extern int32 gps_save_id; extern double gps_save_version; extern char gps_save_string[GPS_ARB_LEN]; extern int gps_is_usb; +extern int gps_baud_rate; extern struct COMMANDDATA COMMAND_ID[2]; extern struct LINKDATA LINK_ID[3]; diff --git a/gpsbabel/jeeps/gpsapp.cc b/gpsbabel/jeeps/gpsapp.cc index 17e7002e9..ebebfe554 100644 --- a/gpsbabel/jeeps/gpsapp.cc +++ b/gpsbabel/jeeps/gpsapp.cc @@ -36,6 +36,7 @@ */ #include "garminusb.h" #include "gpsusbint.h" +#include "gpsserial.h" time_t gps_save_time; double gps_save_lat; @@ -3655,7 +3656,7 @@ static void GPS_D210_Send(UC* data, GPS_PWay way, int32* len) ** ** @return [int32] number of track entries ************************************************************************/ -int32 GPS_A300_Get(const char* port, GPS_PTrack** trk, pcb_fn cb) +int32 GPS_A300_Get(const char* port , GPS_PTrack** trk, pcb_fn) { static UC data[2]; gpsdevh* fd; @@ -6176,7 +6177,7 @@ int32 GPS_A800_On(const char* port, gpsdevh** fd) ** ** @return [int32] success ************************************************************************/ -int32 GPS_A800_Off(const char* port, gpsdevh** fd) +int32 GPS_A800_Off(const char*, gpsdevh** fd) { static UC data[2]; GPS_PPacket tra; @@ -6638,7 +6639,7 @@ int32 GPS_A1006_Get ** ** @return [int32] success ************************************************************************/ -int32 GPS_A1006_Send(const char* port, +int32 GPS_A1006_Send(const char*, GPS_PCourse* crs, int32 n_crs, gpsdevh* fd) @@ -6875,7 +6876,7 @@ int32 GPS_A1007_Get(const char* port, GPS_PCourse_Lap** clp, pcb_fn cb) ** ** @return [int32] success ************************************************************************/ -int32 GPS_A1007_Send(const char* port, +int32 GPS_A1007_Send(const char*, GPS_PCourse_Lap* clp, int32 n_clp, gpsdevh* fd) @@ -7150,7 +7151,7 @@ int32 GPS_A1008_Get(const char* port, GPS_PCourse_Point** cpt, pcb_fn cb) ** ** @return [int32] success ************************************************************************/ -int32 GPS_A1008_Send(const char* port, +int32 GPS_A1008_Send(const char*, GPS_PCourse_Point* cpt, int32 n_cpt, gpsdevh* fd) @@ -7641,3 +7642,23 @@ void GPS_Prepare_Track_For_Device(GPS_PTrack** trk, int32* n) } } } + +int32 GPS_Set_Baud_Rate(const char* port, int br) +{ + + gpsdevh* fd; + + if (!GPS_Device_On(port, &fd)) { + return gps_errno; + } + + if (gps_is_usb) return -1; // this feature is serial only + GPS_Serial_Set_Baud_Rate(fd, br); + + if (!GPS_Device_Off(fd)) { + return gps_errno; + } + + return 0; + +} diff --git a/gpsbabel/jeeps/gpsapp.h b/gpsbabel/jeeps/gpsapp.h index 7933a43ca..f9e9b17ab 100644 --- a/gpsbabel/jeeps/gpsapp.h +++ b/gpsbabel/jeeps/gpsapp.h @@ -110,5 +110,6 @@ const char* Get_Pkt_Type(US p, US d0, const char** xinfo); void GPS_Prepare_Track_For_Device(GPS_PTrack** trk, int32* n); + int32 GPS_Set_Baud_Rate(const char* port, int br); #endif diff --git a/gpsbabel/jeeps/gpscom.cc b/gpsbabel/jeeps/gpscom.cc index 8caa2f1a1..bcd686df9 100644 --- a/gpsbabel/jeeps/gpscom.cc +++ b/gpsbabel/jeeps/gpscom.cc @@ -1306,7 +1306,7 @@ int32 GPS_Command_Send_Track_As_Course(const char* port, GPS_PTrack* trk, int32 } /*Stubs for unimplemented stuff*/ -int32 GPS_Command_Get_Workout(const char* port, void** lap, int (*cb)(int, struct GPS_SWay**)) +int32 GPS_Command_Get_Workout(const char*, void**, int (*cb)(int, struct GPS_SWay**)) { return 0; } diff --git a/gpsbabel/jeeps/gpsserial.cc b/gpsbabel/jeeps/gpsserial.cc index 19ef8f8fd..0e0c4a031 100644 --- a/gpsbabel/jeeps/gpsserial.cc +++ b/gpsbabel/jeeps/gpsserial.cc @@ -33,6 +33,8 @@ #include #include +int gps_baud_rate = DEFAULT_BAUD; + #if 0 #define GARMULATOR 1 char* rxdata[] = { @@ -226,6 +228,7 @@ int32 GPS_Serial_Read(gpsdevh* dh, void* ibuf, int size) #else +#include "../gbser_posix.h" #include #include #include @@ -249,6 +252,8 @@ typedef struct { int32 GPS_Serial_Open(gpsdevh* dh, const char* port) { struct termios tty; + if (global_opts.debug_level >= 2) fprintf(stderr, "GPS Serial Open at %d\n", gps_baud_rate); + speed_t baud = mkspeed(gps_baud_rate); posix_serial_data* psd = (posix_serial_data*)dh; /* @@ -272,8 +277,8 @@ int32 GPS_Serial_Open(gpsdevh* dh, const char* port) tty.c_cflag &= ~(CSIZE); tty.c_cflag |= (CREAD | CS8 | CLOCAL); - cfsetospeed(&tty,B9600); - cfsetispeed(&tty,B9600); + cfsetospeed(&tty,baud); + cfsetispeed(&tty,baud); tty.c_lflag &= 0x0; tty.c_iflag &= 0x0; @@ -527,4 +532,87 @@ int32 GPS_Serial_Off(gpsdevh* dh) return 1; } +// Based on information by Kolesár András from +// http://www.manualslib.com/manual/413938/Garmin-Gps-18x.html?page=32 +int32 GPS_Serial_Set_Baud_Rate(gpsdevh* fd, int br) +{ + + struct termios tty; + static UC data[4]; + GPS_PPacket tra; + GPS_PPacket rec; + speed_t speed; + + speed = mkspeed(br); + + // Turn off all requests by transmitting packet + GPS_Util_Put_Short(data, 0); + GPS_Make_Packet(&tra, 0x1c, data, 2); + if (!GPS_Write_Packet(fd,tra)) { + return gps_errno; + } + if (!GPS_Get_Ack(fd, &tra, &rec)) { + return gps_errno; + } + + GPS_Util_Put_Int(data, br); + GPS_Make_Packet(&tra, 0x30, data, 4); + if (!GPS_Write_Packet(fd,tra)) { + return gps_errno; + } + if (!GPS_Get_Ack(fd, &tra, &rec)) { + return gps_errno; + } + + // Receive IOP_BAUD_ACPT_DATA + if (!GPS_Packet_Read(fd, &rec)) { + return gps_errno; + } + + // Acnowledge new speed + if (!GPS_Send_Ack(fd, &tra, &rec)) { + return gps_errno; + } + GPS_Device_Flush(fd); + GPS_Device_Wait(fd); + + // Sleep for a small amount of time, about 100 milliseconds, + // to make sure the packet was successfully transmitted to the GPS unit. + gb_sleep(100000); + + // Change port speed + posix_serial_data* psd = (posix_serial_data*)fd; + tty = psd->gps_ttysave; + + cfsetospeed(&tty,speed); + cfsetispeed(&tty,speed); + + if (tcsetattr(psd->fd,TCSANOW|TCSAFLUSH,&tty)==-1) { + GPS_Serial_Error("SERIAL: tcsetattr error"); + return 0; + } + + GPS_Util_Put_Short(data, 0x3a); + GPS_Make_Packet(&tra, 0x0a, data, 2); + if (!GPS_Write_Packet(fd,tra)) { + return gps_errno; + } + if (!GPS_Get_Ack(fd, &tra, &rec)) { + return gps_errno; + } + + GPS_Util_Put_Short(data, 0x3a); + GPS_Make_Packet(&tra, 0x0a, data, 2); + if (!GPS_Write_Packet(fd,tra)) { + return gps_errno; + } + if (!GPS_Get_Ack(fd, &tra, &rec)) { + return gps_errno; + } + + if (global_opts.debug_level >= 1) fprintf(stderr, "Serial port speed set to %d\n", br); + return 0; + +} + #endif /* __WIN32__ */ diff --git a/gpsbabel/jeeps/gpsserial.h b/gpsbabel/jeeps/gpsserial.h index 9507ded8c..a9f13dae3 100644 --- a/gpsbabel/jeeps/gpsserial.h +++ b/gpsbabel/jeeps/gpsserial.h @@ -5,6 +5,7 @@ #include "gps.h" #define usecDELAY 180000 /* Microseconds before GPS sends A001 */ +#define DEFAULT_BAUD 9600 int32 GPS_Serial_Chars_Ready(gpsdevh* fd); // int32 GPS_Serial_Close(int32 fd, const char *port); @@ -22,6 +23,6 @@ int32 GPS_Serial_Write_Packet(gpsdevh* fd, GPS_PPacket& packet); int32 GPS_Serial_Send_Ack(gpsdevh* fd, GPS_PPacket* tra, GPS_PPacket* rec); void GPS_Serial_Error(const char* hdr, ...); - + int32 GPS_Serial_Set_Baud_Rate(gpsdevh* fd, int br); #endif diff --git a/gpsbabel/jeeps/gpsusbread.cc b/gpsbabel/jeeps/gpsusbread.cc index 5e392beee..233f08587 100644 --- a/gpsbabel/jeeps/gpsusbread.cc +++ b/gpsbabel/jeeps/gpsusbread.cc @@ -28,7 +28,7 @@ * Negative on error. * 1 if read success - even if empty packet. */ -int32 GPS_Packet_Read_usb(gpsdevh* dh, GPS_PPacket* packet, int eat_bulk) +int32 GPS_Packet_Read_usb(gpsdevh*, GPS_PPacket* packet, int eat_bulk) { int32 n; int32 payload_size; diff --git a/gpsbabel/jeeps/gpsusbsend.cc b/gpsbabel/jeeps/gpsusbsend.cc index 45c0edef6..de433adff 100644 --- a/gpsbabel/jeeps/gpsusbsend.cc +++ b/gpsbabel/jeeps/gpsusbsend.cc @@ -26,7 +26,7 @@ #include "gpsusbint.h" int32 -GPS_Write_Packet_usb(gpsdevh* dh, GPS_PPacket& packet) +GPS_Write_Packet_usb(gpsdevh*, GPS_PPacket& packet) { garmin_usb_packet gp; memset(&gp, 0, sizeof(gp)); diff --git a/gpsbabel/xmldoc/formats/options/garmin-baud.xml b/gpsbabel/xmldoc/formats/options/garmin-baud.xml new file mode 100644 index 000000000..04eb09b24 --- /dev/null +++ b/gpsbabel/xmldoc/formats/options/garmin-baud.xml @@ -0,0 +1,28 @@ + +Sets baud rate on some Garmin serial unit to the specified baud rate. Garmin protocol uses 9600 bps by default, but there is a rarely documented feature in Garmin binary protocol for switching baud rate. Highest option is 115200. + + + +Download track log and waypoints 12 times faster than default: + +gpsbabel -t -w -i garmin,baud=115200 -f /dev/ttyUSB0 -o gpx -F garmin-serial.gpx + + + + +At the end of the transfer, baud rate is switched to back to the default +of 9600. If connection breaks, the unit stucks at high baud rate, a power +cycle reverts to original state. + + + +This option does not affect USB transfer. + + + +Because this feature uses undocumented Garmin protocols, it may or may +not work on your device. The author reported success with +eTrex Vista, GPSMAP 76s, and GPS V, but it seems likely to be problematic +on older units and may be more problematic for writing to the device than +reading data from the device. + -- 2.30.2